#! /usr/bin/perl -w

# TODO: this should really be converted into an ant build.xml

use strict;
use Carp;
use File::Path;
use File::Copy;
use Cwd;
use File::Basename;

# TODO: Add GUID as parameter

my $cwd = &Cwd::cwd();

my $EXTENSION_SRC_DIR = $cwd.'/src';
my $BUILD_DIR         = $cwd.'/dist';

my $TO_BUILD_DIR   = $BUILD_DIR.'/to_build';
my $TO_UPLOAD_DIR  = $BUILD_DIR.'/to_upload';

my $INSTALL_RDF     = $TO_BUILD_DIR.'/install.rdf';
my $CHROME_MANIFEST = $TO_BUILD_DIR.'/chrome.manifest';

my $MASTER_UPDATE_RDF  = $BUILD_DIR.'/NoCache/update.rdf';
my $UPDATE_RDF         = $TO_UPLOAD_DIR.'/NoCache/update.rdf';

my $MASTER_BOUNCE_HTACCESS = $BUILD_DIR.'/bounce/DOT_htaccess.txt';
my $BOUNCE_HTACCESS        = $TO_UPLOAD_DIR.'/bounce/.htaccess';

my $ARCHIVE_DIR = $BUILD_DIR.'/archive';

my $EXTENSION_NAME='ViewMyCurrency';
my $about_html   = "$TO_BUILD_DIR/chrome/viewmycurrency/content/about/WILL_about.html";
my $overlay_dtd  = "$TO_BUILD_DIR/chrome/viewmycurrency/locale/en-US/WILL_ViewMyCurrencyOverlay.dtd";

my $BLOG_URL     = "http://viewmycurrency.wordpress.com/tag/releases/";

my $TEST_RELEASE = 0;
if (@ARGV) {
    warn "\n\n  ** Building test release. Press return to continue: ** \n";
    <STDIN>;
    $TEST_RELEASE = 1;
}

rmtree($TO_BUILD_DIR);
mkpath($TO_BUILD_DIR);

my ($EXTENSION_VERSION, $ALPHA_RELEASE)=&getVersion("$EXTENSION_SRC_DIR/chrome/viewmycurrency/content/WILL_Helpers.js");

my $UPDATELINK="http://hamstersoup.com/$EXTENSION_NAME/${EXTENSION_NAME}_v${EXTENSION_VERSION}.xpi";

&copyExtensionSrcDir;
&updateFile($INSTALL_RDF,'VERSION','ALPHA');
&updateFile($about_html,'VERSION','ALPHA','TEST');
&updateFile($overlay_dtd,'VERSION');

&updateFile($CHROME_MANIFEST,'JAR');
&create_jarfile();

&createXpi;
rmtree($TO_UPLOAD_DIR);

warn "\n\n ** New XPI is now ready for testing in $TO_BUILD_DIR **\n";
warn "  ** If it's OK then write the release notes at $BLOG_URL and press return: \n";
<STDIN>;
&createUploaddir;
&updateFile($UPDATE_RDF,'UPDATELINK','VERSION');
my $LATEST_RELEASE_URL=&getLatestReleaseUrl();
&updateFile($BOUNCE_HTACCESS,'VERSION','GIVEFEEDBACK');

&copyXPIs;

&cvsTagRelease;

warn "\n\nFinished. Don't forget to check the About Dialog redirects work OK\n\n";

exit(0);

sub cvsTagRelease {
    die "DO TAGGING?";
    my $tag = "v$EXTENSION_VERSION";
    $tag =~ s/\./_/g; # dots are not allowed in tags
    my $cmd = "cvs tag $tag";
    
    do {
	warn "\n\nType 'tag' to do '$cmd' after release\n";    
    } while (<STDIN> !~ /tag/);
    
    chdir($EXTENSION_SRC_DIR);
    system($cmd);
}

sub getVersion {
    my ($file)=@_;
    my $contents=getFile($file);
    # Look for this string: this.VERSION = 0.387;  // alpha-version!
    $contents =~ /this\.VERSION = (\d+\.\d+)/ || croak "Could not find version in $file";
    my $ver = $1;
    if (!$ver || $ver<=0 || $ver>=1) { croak "Is version [$ver] correct?"; }

    my $alpha=0;
    if ( ($ver*1000) % 10 ) {
	$alpha=1;
    } else {
	warn "This is a PUBLIC release - it better be good!\n";
    }
    
    return ($ver,$alpha);
}

    
sub copyExtensionSrcDir {
    #This doesn't work for dirs: copy($EXTENSION_SRC_DIR,$TO_BUILD_DIR) || croak("Could not copy $EXTENSION_SRC_DIR to $TO_BUILD_DIR");
    # So we have to create temp archive :-(
    my $archive='temp.7z';
    chdir($EXTENSION_SRC_DIR);

    print "\n\nReview hacks:\n";
    system("make hack");
    print "\nPress return to continue:\n";
    $_=<STDIN>;


    my $excludeTests="";
    $excludeTests = "-x\!jsunit -x\!tests" unless $TEST_RELEASE;
	
    # exclude jsunit, the unit tests and the uninstall dir
    # exclude backups~ #emacs_files# .cvsignore TAGS Makefile Changelog
    system("7z -r -x\!.svn  $excludeTests -x\!uninstall -x\!*~ -x\!#*# -x\!TAGS -x\!Makefile -x\!ChangeLog a $archive * |tee /tmp/7z.log");
    move($archive,$TO_BUILD_DIR);
    chdir($TO_BUILD_DIR);
    system("7z x $archive | tee -a /tmp/7z.log");
    unlink($archive);

}

sub updateFile {
    my ($filename,@todo)=@_;
    my $text =&getFile($filename);

    while($_ = shift(@todo)) {
	if    ($_ eq 'VERSION')      { $text = &replaceVERSION($text,$filename); }
	elsif ($_ eq 'ALPHA')        { $text = &removeALPHAforOffical($text,$filename); }
	elsif ($_ eq 'GIVEFEEDBACK') { $text = &replaceGIVEFEEDBACK($text,$filename); }
	elsif ($_ eq 'TEST')         { $text = &removeTESTforNonTest($text,$filename); }
	elsif ($_ eq 'UPDATELINK')   { $text = &replaceOrRemoveUPDATELINK($text,$filename); } 
	elsif ($_ eq 'JAR')          { $text = &replaceChromeJar($text,$filename); }
	else                         { croak "Unknown action $_ "; }
    }

    &putFile($filename,$text);
}

sub createXpi {
    chdir($TO_BUILD_DIR);
    system("7z a -tzip $EXTENSION_NAME.xpi * -r -mx=9");
}

#WILL: HACK: hard coded extension name. Consider importance of case
sub create_jarfile {
    chdir($TO_BUILD_DIR);
    chdir("chrome");
    chdir("viewmycurrency");
    system("7z a -tzip ../viewmycurrency.jar * -r -mx=0");
    chdir("..");
    system("rm -rf viewmycurrency");
}


sub createUploaddir {    
    mkpath(dirname($UPDATE_RDF));

    # Copy the update.rdf file to the NoCache subdirectory
    #Watch out for \ in double quotes!
    copy($MASTER_UPDATE_RDF,$UPDATE_RDF) || croak("problem with copy");

    # Copy the bounce/.htaccess file
    mkpath(dirname($BOUNCE_HTACCESS));
    -e $MASTER_BOUNCE_HTACCESS || croak "Missing $MASTER_BOUNCE_HTACCESS";
    -e $BOUNCE_HTACCESS && croak "$BOUNCE_HTACCESS already exists!";
    copy($MASTER_BOUNCE_HTACCESS,$BOUNCE_HTACCESS) || croak("problem with copy");    
}




sub copyXPIs {
    chdir($TO_BUILD_DIR);
    copy("$EXTENSION_NAME.xpi","$TO_UPLOAD_DIR/$EXTENSION_NAME.xpi");
    copy("$EXTENSION_NAME.xpi","$TO_UPLOAD_DIR/${EXTENSION_NAME}_v${EXTENSION_VERSION}.xpi");
    copy("$EXTENSION_NAME.xpi","$ARCHIVE_DIR/${EXTENSION_NAME}_v${EXTENSION_VERSION}.xpi");
}

exit(0);



sub getFile {
    my ($filename) = @_;
    open(INPUT,$filename) || croak("Could not open $filename");
    my $temp=$/;
    undef $/;
    my $content = <INPUT>;
    close(INPUT);
    $/ = $temp;     #Restore for normal behaviour later in script
    return $content;
}

sub putFile {
    my ($filename,$text)=@_;
    open(OUTPUT,">$filename") || croak("Could not open $filename for writing");
    print OUTPUT $text;
    close(OUTPUT);
}

#sub increment {
#    my ($filename)=@_;
#    my $text=&getFile($filename);
#    $text =~ /([\d\.]+)/ || croak("Could not find version number in $filename");
#    my $ver=$1;
#    $ver=$ver+0.001;
#    &putFile($filename,"$EXTENSION_NAME version=$ver");
#    print "$EXTENSION_NAME version=$ver\n";
#    return $ver;
#};


                              #####################
                              # Replace functions #
                              #####################


sub getLatestReleaseUrl() {
    my $htmlFile = '/tmp/viewmycurrency_releases.html';
    my $errFile  = '/tmp/viewmycurrency_wgetErr.txt';
    my $cmd="wget  --output-file=$errFile  --output-document=$htmlFile $BLOG_URL ";
    system($cmd);
    -e $htmlFile || die "Did not download $htmlFile";
    my $output=`grep --after-context=4 entry $htmlFile | head -4 | grep href`;
    # grab URL like this: http://viewmycurrency.wordpress.com/2006/02/08/firefox-currency-converter-viewmycurrency-0389-alpha-released/"
    $output =~ /href=\"(.+?)\"/ || die "Could not find latest release URL in $output\nCmd was $cmd";
    warn "Latest Release URL: $1\n";
    return $1;
}

sub replaceOrRemoveUPDATELINK()   {
    my $newStr = $ALPHA_RELEASE ? "<updateLink>$UPDATELINK<\/updateLink>" : ""; # replace or remove
    return &genericReplace('', @_ , '<!--UPDATELINK(.+?)UPDATELINK-->', $newStr );
}

sub replaceGIVEFEEDBACK()   { return &genericReplace('',             @_ , '<!--GIVEFEEDBACK(.+?)GIVEFEEDBACK-->', $LATEST_RELEASE_URL ); }
sub replaceVERSION()        { return &genericReplace('',             @_ , '<?!--VERSION(.+?)VERSION-->?',         $EXTENSION_VERSION  ); }
sub removeALPHAforOffical() { return &genericReplace($ALPHA_RELEASE, @_ , '<!--ALPHA-->(.|\s)*?<!--ALPHA-->',     ''                  ); }
sub removeTESTforNonTest()  { return &genericReplace($TEST_RELEASE,  @_,  '<!--TESTS-->((.|\s)*?)<!--TESTS-->',   ''                  ); }
sub replaceChromeJar()      { return &genericReplace('',             @_,  '(chrome\/viewmycurrency)(?!\.jar)',             'jar:chrome/viewmycurrency.jar!' ); }


sub genericReplace() {
    my ($skip,$text,$filename,$regExp,$newStr)=@_;
    $skip && return $text; # don't remove, this is a test, or an alpha or something.

    $filename=basename($filename);
    my $foundIt=0;
    while ($text =~ /$regExp/g) {
	$foundIt=1;
	$text =~ s/$regExp/$newStr/ || croak "Replace failed: $regExp --> $newStr";
	warn "REPLACE: $filename:\t Set $regExp [$1] --> [$newStr]\n";
    }
    $foundIt || croak "Failed to find $regExp in $filename"; 
    return $text;
}
